package com.evil.application.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.evil.account.api.RemoteUserService;
import com.evil.application.api.RemoteApplicationOrderLogService;
import com.evil.application.mapper.*;
import com.evil.application.pojo.dto.order.log.AddOrderLogReqDTO;
import com.evil.application.pojo.dto.order.log.AddRobotLogReqDTO;
import com.evil.application.pojo.dto.order.log.OrderLogRespDTO;
import com.evil.application.pojo.dto.order.log.OrderNodeAssigneeDTO;
import com.evil.application.pojo.dto.order.node.handler.QueryOrderNodeHandler;
import com.evil.application.pojo.entity.*;
import com.evil.application.service.ApplicationOrderLogService;
import com.evil.application.service.ApplicationProcessNodeService;
import com.evil.application.util.ApplicationUtil;
import com.evil.common.account.dto.user.UserBaseRespDTO;
import com.evil.common.account.util.LoginUtil;
import com.evil.common.activiti.enums.HandleTypeEnum;
import com.evil.common.activiti.enums.NodeTypeEnum;
import com.evil.common.application.enums.order.OrderProcessStatusEnum;
import com.evil.common.core.util.StreamUtil;
import com.evil.common.family.dto.FindByIdsReqDTO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 应用订单日志表
 *
 * @author liyang
 * @date 2022-08-08 00:00
 */
@Slf4j
@RestController
@AllArgsConstructor
public class ApplicationOrderLogServiceImpl extends ServiceImpl<ApplicationOrderLogMapper, ApplicationOrderLog>
        implements ApplicationOrderLogService, RemoteApplicationOrderLogService {

    private final LoginUtil loginUtil;

    private final ApplicationOrderMapper applicationOrderMapper;

    private final ApplicationProcessNodeMapper applicationProcessNodeMapper;

    private final ApplicationOrderNodeMapper applicationOrderNodeMapper;

    private final ApplicationOrderNodeHandlerMapper applicationOrderNodeHandlerMapper;

    private final ApplicationProcessNodeService applicationProcessNodeService;

    private final RemoteUserService remoteUserService;

    private final ApplicationLogServiceImpl applicationLogService;

    /**
     * 订单日志
     *
     * @param orderId orderId
     * @return List
     */
    @Override
    public List<OrderLogRespDTO> orderLog(Long orderId) {
        ApplicationOrder order = applicationOrderMapper.findById(orderId);
        OrderProcessStatusEnum orderProcessStatusEnum = OrderProcessStatusEnum.findById(order.getProcessStatus());

        // 订单节点日志
        List<OrderLogRespDTO> orderLogs = this.baseMapper.findByOrderId(orderId).stream()
                .map(e -> {
                    OrderLogRespDTO orderLogRespDTO = new OrderLogRespDTO(e);
                    if (StringUtils.isNotBlank(e.getAssignee())) {
                        List<OrderNodeAssigneeDTO> assignees = JSON.parseArray(e.getAssignee(), OrderNodeAssigneeDTO.class);
                        // 处理人
                        orderLogRespDTO.setHandlerIds(assignees.stream().map(OrderNodeAssigneeDTO::getHandlerId).toList());
                    }
                    return orderLogRespDTO;
                })
                .collect(Collectors.toList());

        // 订单处理中节点日志
        orderLogs.addAll(this.orderProcessingNodeLog(orderId));

        // 获取节点名称Map
        Set<Long> nodeIds = new HashSet<>();
        Set<Long> handlerIds = new HashSet<>();
        orderLogs.forEach(log -> {
            nodeIds.add(log.getNodeId());
            handlerIds.addAll(log.getHandlerIds());
        });

        // 节点名称
        List<ApplicationProcessNode> nodes = applicationProcessNodeMapper.findByIds(nodeIds, false);
        Map<Long, String> nodeNameMap = StreamUtil.toMapKV(nodes, ApplicationProcessNode::getNodeId, e -> {
            if (NodeTypeEnum.END_EVENT.getId() == e.getNodeType()) {
                return orderProcessStatusEnum.getName();
            } else {
                return e.getNodeName();
            }
        });
        Map<Long, UserBaseRespDTO> handlerMap = remoteUserService.findBaseMapByIds_Default(FindByIdsReqDTO.unFilter(handlerIds));

        orderLogs.forEach(log -> {
            log.setNodeName(nodeNameMap.getOrDefault(log.getNodeId(), OrderProcessStatusEnum.PROCESSING.getName()));
            log.setAssignee(log.getHandlerIds().stream().filter(handlerMap::containsKey).map(handlerMap::get).toList());
        });
        return orderLogs;
    }

    /**
     * 新增订单节点日志
     *
     * @param addRobotLogReqDTO addRobotLogReqDTO
     */
    @Override
    public void addOrderLog(AddRobotLogReqDTO addRobotLogReqDTO) {
        Long orderId = addRobotLogReqDTO.getOrderId();
        Long nodeId = addRobotLogReqDTO.getNodeId();
        Integer handleType = addRobotLogReqDTO.getHandleType();
        String remark = addRobotLogReqDTO.getRemark();

        HandleTypeEnum.findById(handleType);
        applicationOrderMapper.findById(orderId);
        applicationProcessNodeMapper.findById(nodeId, false);

        OrderNodeAssigneeDTO assignee;
        if (addRobotLogReqDTO instanceof AddOrderLogReqDTO) {
            AddOrderLogReqDTO addOrderLogReqDTO = (AddOrderLogReqDTO) addRobotLogReqDTO;
            Long handlerId = addOrderLogReqDTO.getHandlerId();
            // 获取订单节点处理人
            QueryOrderNodeHandler queryOrderNodeHandler = new QueryOrderNodeHandler(orderId, nodeId);
            List<ApplicationOrderNodeHandler> nodeHandlers = applicationOrderNodeHandlerMapper.queryOrderNodeHandler(queryOrderNodeHandler);
            // 获取指定用户（登陆人）处理节点，不存在抛出异常
            ApplicationOrderNodeHandler nodeHandler = ApplicationUtil.nodeHandler(nodeHandlers, handlerId, handleType, loginUtil::getLoginUserId);
            assignee = BeanUtil.copyProperties(nodeHandler, OrderNodeAssigneeDTO.class);
        } else {
            // 机器人
            Long handlerId = StreamUtil.findFirst(applicationProcessNodeService.getNodeHandlers(addRobotLogReqDTO)).getUserId();
            UserBaseRespDTO handler = remoteUserService.findBaseById(handlerId);
            assignee = new OrderNodeAssigneeDTO(handlerId, handler.getNickName(), "1");
        }

        // 添加处理日志
        ApplicationOrderLog applicationOrderLog = new ApplicationOrderLog();
        applicationOrderLog.setOrderId(orderId);
        applicationOrderLog.setNodeId(nodeId);
        applicationOrderLog.setAssignee(JSON.toJSONString(ListUtil.toList(assignee)));
        applicationOrderLog.setHandleType(handleType);
        applicationOrderLog.setHandleDate(new Date());
        applicationOrderLog.setRemark(remark);
        applicationLogService.saveAndCheck(this.baseMapper, ApplicationOrderLog::getOrderLogId, applicationOrderLog);
    }

    /**
     * 新增订单节点日志
     *
     * @param addRobotLogReqDTO addRobotLogReqDTO
     * @param assignee          assignee
     */
    @Override
    public void addOrderLog(AddRobotLogReqDTO addRobotLogReqDTO, OrderNodeAssigneeDTO assignee) {
        // 添加处理日志
        ApplicationOrderLog applicationOrderLog = new ApplicationOrderLog();
        applicationOrderLog.setOrderId(addRobotLogReqDTO.getOrderId());
        applicationOrderLog.setNodeId(addRobotLogReqDTO.getNodeId());
        applicationOrderLog.setAssignee(JSON.toJSONString(ListUtil.toList(assignee)));
        applicationOrderLog.setHandleType(addRobotLogReqDTO.getHandleType());
        applicationOrderLog.setHandleDate(new Date());
        applicationOrderLog.setRemark(addRobotLogReqDTO.getRemark());
        applicationLogService.saveAndCheck(this.baseMapper, ApplicationOrderLog::getOrderLogId, applicationOrderLog);
    }

    /**
     * 订单处理中节点日志
     *
     * @param orderId orderId
     * @return OrderLogRespDTO 列表
     */
    private List<OrderLogRespDTO> orderProcessingNodeLog(Long orderId) {
        // 处理中
        int processing = HandleTypeEnum.PROCESSING.getId();
        // 订单处理中节点处理人
        Map<Long, List<ApplicationOrderNodeHandler>> nodeHandlersMap = StreamUtil.groupK(
                applicationOrderNodeHandlerMapper.findProcessingOrderNode(orderId, processing), ApplicationOrderNodeHandler::getNodeId);
        // 订单处理中节点
        List<ApplicationOrderNode> orderNodes = applicationOrderNodeMapper.findProcessingOrderNode(orderId, processing);
        return StreamUtil.transListT(orderNodes, e -> {
            OrderLogRespDTO orderLogRespDTO = new OrderLogRespDTO();
            orderLogRespDTO.setOrderLogId(e.getOrderNodeId());
            orderLogRespDTO.setOrderId(e.getOrderId());
            orderLogRespDTO.setNodeId(e.getNodeId());
            orderLogRespDTO.setHandleType(e.getHandleType());

            List<ApplicationOrderNodeHandler> nodeHandlers = nodeHandlersMap.getOrDefault(e.getNodeId(), new ArrayList<>());
            orderLogRespDTO.setHandlerIds(StreamUtil.transListT(nodeHandlers, ApplicationOrderNodeHandler::getHandlerId));
            return orderLogRespDTO;
        });
    }
}
